library(rtweet)
library(ggplot2)
library(tidyr)
library(dplyr)
library(tidytext)
library(stringr)
library(scales)
library(readr)
library(lubridate)
library(vader)
library(topicmodels)
library(quanteda)
library(lubridate)
library(zoo)
library(plotly)
library(forcats)
library(igraph)
library(ggraph)
library(widyr)
library(qdapRegex)
library(magick)
library(RedditExtractoR)
reddit_posts <- RedditExtractoR::reddit_urls(search_terms = "Covid", subreddit = "southafrica", page_threshold = 10)
#top words
top_words_reddit <- reddit_media_df %>%
anti_join(stop_words) %>%
count(word) %>%
arrange(desc(n))
Joining, by = "word"
top_words_reddit %>%
slice(1:20) %>%
ggplot(aes(reorder(word,-n), n, fill = word)) +
geom_bar(stat = "identity") +
theme_minimal() +
theme(
axis.text.x = element_text(
angle = 60,
hjust = 1,
size = 13
),
plot.title = element_text(hjust = 0.5, size = 18)
) +
ylab("Frequency") +
xlab ("") +
ggtitle("Most frequent reddit posts") +
guides(fill = FALSE)

#bigrams
reddit_bigram_df <- reddit_posts_df %>%
#filter(str_detect(text, fixed(covid_dictionary, ignore_case = TRUE))) %>%
filter(!str_detect(title, "^RT")) %>%
mutate(title = gsub(" ?(f|ht)tp(s?)://(.*)[.][a-z]+", " ", title)) %>%
unnest_tokens(bigram, title, token = "ngrams", n = 2) %>%
separate(bigram, c("word1", "word2"), sep = " ")
reddit_bigrams_filtered <- reddit_bigram_df %>%
filter(!word1 %in% stop_words$word) %>%
filter(!word2 %in% stop_words$word)
# new bigram counts:
reddit_bigram_counts <- reddit_bigrams_filtered %>%
count(word1, word2, sort = TRUE)
reddit_bigrams_united <- reddit_bigrams_filtered %>%
unite(bigram, word1, word2, sep = " ")
#weights and graphs
reddit_bigram_graph <- reddit_bigram_counts %>%
filter(n > 100) %>%
graph_from_data_frame()

reddit_section_words <- reddit_media_df %>%
mutate(section = row_number() %/% 10) %>%
filter(section > 0)
# count words co-occuring within sections
reddit_word_pairs <- reddit_section_words %>%
pairwise_count(word, section, sort = TRUE)
# we need to filter for at least relatively common words first
reddit_word_cors <- reddit_section_words %>%
group_by(word) %>%
filter(n() >= 20) %>%
pairwise_cor(word, section, sort = TRUE)
reddit_word_cors %>%
slice_max(correlation, n = 6) %>%
mutate(item2 = reorder(item2, correlation)) %>%
ggplot(aes(item2, correlation)) +
geom_bar(stat = "identity") +
facet_wrap( ~ item1, scales = "free") +
coord_flip()

set.seed(1234)
reddit_word_cors %>%
graph_from_data_frame() %>%
ggraph(layout = "fr") +
geom_edge_link(aes(edge_alpha = correlation),
show.legend = FALSE,
edge_width = 3) +
geom_node_point(color = "lightblue", size = 5) +
geom_node_text(aes(label = name), repel = TRUE) +
theme_void()

# vader_df <- vader_df(reddit_posts_df$title)
# write_as_csv(vader_df, "data_in/vader_reddit_posts")
vader_df <- read_csv("data_in/vader_reddit_posts.csv")
-- Column specification --------------------------------------------------------
cols(
text = col_character(),
word_scores = col_character(),
compound = col_double(),
pos = col_double(),
neu = col_double(),
neg = col_double(),
but_count = col_double()
)
vader_df <- vader_df %>% mutate("X1" = row_number())
reddit_posts_df <- reddit_posts_df %>% mutate("X1" = row_number())
reddit_vader_df <- reddit_posts_df %>% left_join(vader_df, by = "X1")
#General sentiment over time. Media agencies seem to have an even number of positive and negative tweets per day.
ggplot(
reddit_vader_df %>%
mutate(date = as.Date(date)) %>%
group_by(date) %>%
mutate(compound = replace(compound, is.na(compound), 0)) %>%
summarise(sum_compound = sum(as.double(compound))),
aes(date, sum_compound)
) +
geom_bar(stat = "identity") +
geom_smooth(method = "lm", na.rm = TRUE, se = FALSE) +
theme_minimal() +
scale_y_continuous(expand = c(0, 0)) +
scale_x_date(date_breaks = "3 day", date_labels = "%m-%d") +
theme(
axis.text.x = element_text(
angle = 90,
vjust = 0.5,
hjust = 1
),
panel.grid.minor.y = element_blank(),
panel.grid.minor.x = element_blank(),
)

# An illegal gold miner who was severely injured in a clash in which four other illegal miners were killed has been charged for their murders Mpumalanga police said on Thursday
# Italy midfielder Jorginho said team glory is more important than any push to win a surprise Ballon d’Or award for the best player in world football after a teammate said he deserved it
ggplot(
reddit_vader_df %>%
mutate(date = as.Date(date)) %>%
group_by(date) %>%
summarise(compound),
aes(date, compound)
) +
geom_bar(stat = "identity") +
geom_smooth(method = "lm", na.rm = TRUE) +
theme_minimal() +
scale_y_continuous(expand = c(0, 0))
`summarise()` has grouped output by 'date'. You can override using the `.groups` argument.

#News sentiment
reddit_vader_df %>%
mutate(date = as.Date(date)) %>%
group_by(date) %>%
summarise(compound) %>%
arrange(desc(compound))
`summarise()` has grouped output by 'date'. You can override using the `.groups` argument.
ggplot(reddit_vader_df %>% arrange(compound) %>% mutate(X1 = factor(X1, levels = X1)),
aes(x = X1)) +
geom_point(mapping = aes(y = compound)) +
theme_minimal() +
scale_y_continuous(expand = c(0, 0))

reddit_vader_df %>%
mutate(date = as.Date(date)) %>%
group_by(date) %>%
mutate(compound = replace(compound, is.na(compound), 0)) %>%
summarise(sum_compound = sum(as.double(compound)))
reddit_matrix <-
reddit_media_df %>% sample(size = 0.1) %>% count(subreddit, word) %>% cast_dfm(subreddit, word, n)
Error: Must group by variables found in `.data`.
* Column `subreddit` is not found.
* Column `word` is not found.
Run `rlang::last_error()` to see where the error occurred.
library("ldatuning")
library("topicmodels")
data("AssociatedPress", package = "topicmodels")
dtm <- AssociatedPress[1:10,]
result <- FindTopicsNumber(
reddit_matrix,
topics = seq(from = 2, to = 15, by = 1),
metrics = c("Griffiths2004", "CaoJuan2009", "Arun2010", "Deveaud2014"),
method = "Gibbs",
control = list(seed = 77),
mc.cores = 2L,
verbose = TRUE
)
FindTopicsNumber_plot(result)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBTRVRVUH0NCmxpYnJhcnkocnR3ZWV0KQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHl0ZXh0KQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHZhZGVyKQ0KbGlicmFyeSh0b3BpY21vZGVscykNCmxpYnJhcnkocXVhbnRlZGEpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoem9vKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGZvcmNhdHMpDQpsaWJyYXJ5KGlncmFwaCkNCmxpYnJhcnkoZ2dyYXBoKQ0KbGlicmFyeSh3aWR5cikNCmxpYnJhcnkocWRhcFJlZ2V4KQ0KbGlicmFyeShtYWdpY2spDQpgYGANCg0KYGBge3IgRmV0Y2hpbmcgUG9zdHN9DQpsaWJyYXJ5KFJlZGRpdEV4dHJhY3RvUikNCnJlZGRpdF9wb3N0cyA8LSBSZWRkaXRFeHRyYWN0b1I6OnJlZGRpdF91cmxzKHNlYXJjaF90ZXJtcyA9ICJDb3ZpZCIsIHN1YnJlZGRpdCA9ICJzb3V0aGFmcmljYSIsIHBhZ2VfdGhyZXNob2xkID0gMTApDQoNCndyaXRlX2FzX2NzdihyZWRkaXRfcG9zdHMsICJkYXRhX2luL3JlZGRpdF9wb3N0cyIpDQpgYGANCg0KYGBge3IgQ2xlYW4gdXAsIGluY2x1ZGU9RkFMU0V9DQojY3JlYXRlZCBpZiBtb3JlIHBvc3RzIGNvdWxkIGJlIGFjY2Vzc2VkIHRvIGJlIG1vcmUgdG9waWMgc3BlY2lmaWMNCiMgY292aWRfZGljdGlvbmFyeSA8LSBjKCJoZXJkIiwgImltbXVuaXR5IiwgImluY3ViYXRpb24iLCAiam9iIiwgImxvc3MiLCAiS2l0cyIsICJsb2NrZG93biIsICJtYXNrIiwgIk45NSIsICJvdXRicmVhayIsICJwYW5kZW1pYyIsICJxdWFyYW50aW5lIiwgInJlY292ZXJ5IiwgInNhbml0aXNlciIsICJ0cmFuc21pc3Npb24iLCAiVW5kZXJseWluZyIsICJjb25kaXRpb25zIiwgIlZlbnRpbGF0b3JzIiwgIldITyIsICJ4ZW5vcGhvYmlhIiwgInlvdVR1YmUiLCAiem9vbm90aWMiLCAic3RheS1hdC1ob21lIiwgImNvdmlkIiwgImNvcm9uYXZpcnVzIiwgImh5cmRveHljaGxvcm9xdWluZSIsICJhc3ltcHRvbWF0aWMiLCAiZnJvbnRsaW5lIiwgInZpcnVzIiwgInNlbGYtaXNvbGF0aW9uIiwgImRpc2luZmVjdGFudCIsICJzaGVsdGVyLWluLXBsYWNlIiwgIm1hc2tzIiwgIlNBUlMtQ29WLTIiLCAiSUNVIiwgImNvcm9uYSIsICJyZW9wZW4iLCAiZGlzdGFuY2luZyIsICJjb3ZlcmluZyIsICJmdXJsb3VnaCIsICJ0cmFjZXIiLCAiZWFzaW5nIiwgInJlbWRlc2l2aXIiLCAibWFpbC1pbiIsICJob3JuZXQiLCAiYW50aWJvZHkiLCAiaW4tcGVyc29uIiwgImRlZnVuZCIsICJyYWNpc20iLCAibG9vdGluZyIsICJsb290IiwgInJlb3BlbiIsICJ0d28tbWV0cmUiLCAicGFuZGVtaWMiLCAibG9vdGVyIiwgImRpc3RhbmNpbmciLCAiZGV4YW1ldGhhc29uZSIsICJyYWNpYWwiLCAidmFjY2luZSIsICJjdXJmZXciLCJqb2huc3NvbnMiLCAiYXN0cmF6ZW5lY2EiLCAiaG9zcGl0YWxzIiwgInNvY2lhbC1kaXN0YW5jZSIsICJzb2NpYWwtZGlzdGFuY2luZyIsICJwb2xpY2UiLCAicmVndWxhdGlvbnMiLCAic3ltcHRvbXMiLCAidGVzdGluZyIsICJwb3NpdGl2ZS10ZXN0cyIsICJuZWdhdGl2ZS10ZXN0cyIgLCAiY29uZmlybWVkLWNhc2VzIiwgInJlc3RyaWN0aW9ucyIsICJkZWF0aHMiLCAiaW5mZWN0ZWQiLCAicmVjb3ZlcmllcyIsICJsZXZlbCIsICJqb2JzIiwgInVuZW1wbG95ZWQiLCAiZG9jdG9ycyIsICJpbmZlY3Rpb25zIiwgInNhbml0aXNlIiwgInNhbml0aXNlciIsICJzYW5pdGlzYXRpb24iLCAiY29udGFpbm1lbnQiKQ0KDQpyZWRkaXRfcG9zdHNfZGYgPC0gcmVhZF9jc3YoImRhdGFfaW4vcmVkZGl0X3Bvc3RzLmNzdiIpDQpyZWRkaXRfcG9zdHNfZGYgPC0NCiAgcmVkZGl0X3Bvc3RzX2RmWywgY29sU3Vtcyhpcy5uYShyZWRkaXRfcG9zdHNfZGYpKSA8IG5yb3cocmVkZGl0X3Bvc3RzX2RmKV0NCg0KI0pVU1QgdGlkeQ0Kcm1fcmVkZGl0X25fdXJsIDwtDQogIHJtXyhwYXR0ZXJuID0gcGFzdGV4KCJAcm1fdHdpdHRlcl91cmwiLCAiQHJtX3VybCIpKQ0KcmVkZGl0X3Bvc3RzX2RmIDwtIHJlZGRpdF9wb3N0c19kZiAlPiUNCiAgbXV0YXRlKA0KICAgIHRpdGxlID0gcm1fcmVkZGl0X25fdXJsKHRpdGxlKSwNCiAgICB0aXRsZSA9IGdzdWIoIkBcXHcrIiwgIiAiLCB0aXRsZSksDQogICAgdGl0bGUgPSBnc3ViKCJbWzpwdW5jdDpdXSIsICIgIiwgdGl0bGUpLA0KICAgIHRpdGxlID0gZ3N1YigiW1s6ZGlnaXQ6XV0iLCAiICIsIHRpdGxlKSwNCiAgICB0aXRsZSA9IGdzdWIoImh0dHBcXHcrIiwgIiAiLCB0aXRsZSksDQogICAgdGl0bGUgPSBnc3ViKCJbIHxcdF17Mix9IiwgIiAiLCB0aXRsZSksDQogICAgdGl0bGUgPSBnc3ViKCJeICIsICIgIiwgdGl0bGUpLA0KICAgIHRpdGxlID0gZ3N1YigiICQiLCAiICIsIHRpdGxlKSwNCiAgICB0aXRsZSA9IGdzdWIoIl5CVVNJTkVTUyIsICIgIiwgdGl0bGUpLA0KICAgIHRpdGxlID0gZ3N1YigiXldvcmxkIiwgIiAiLCB0aXRsZSkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIHRpdGxlID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlLCAiID8oZnxodCkodHApKHM/KSg6Ly8pKC4qKVsufC9dKC4qKSIsICIgIiksDQogICAgdGl0bGUgPSBzdHJfcmVwbGFjZV9hbGwodGl0bGUsICIgIiwgIiAiKSwNCiAgICB0aXRsZSA9IHN0cl9yZXBsYWNlX2FsbCh0aXRsZSwgIlJUIEBbYS16LEEtWl0qOiAiLCAiICIpLA0KICAgIHRpdGxlID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlLCAiI1thLXosQS1aXSoiLCAiICIpLA0KICAgIHRpdGxlID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlLCAiQFthLXosQS1aXSoiLCAiICIpDQogICkNCg0KI21vc3Qgc3RvcCB3b3JkcyBhcmUgZmlsdGVyZWQgYmFzZWQgb24gdGhlIG1lZGlhIGFnZW5jaWVzIHRhZyBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggVHdlZXQuIGVnLiBXQVRDSDogKmhlYWRsaW5lIGZvbGxvd3MqLg0KcmVkZGl0X3N0b3Bfd29yZHMgPC0NCiAgdGliYmxlKA0KICAgIHdvcmQgPSBjKA0KICAgICAgInNhYmNuZXdzIiwNCiAgICAgICJlbmNhIiwNCiAgICAgICJkc3R2IiwNCiAgICAgICJzYWJja3puIiwNCiAgICAgICJtYXZlcmljayIsDQogICAgICAib3BpbmlvbmlzdGEiLA0KICAgICAgImRtIiwNCiAgICAgICJzY29ycGlvIiwNCiAgICAgICJkc3R2NDAzIiwNCiAgICAgICJpdHVzIiwNCiAgICAgICJydCIsDQogICAgICAiYW1wIiwNCiAgICAgICJ0Z2lmb29kIiwNCiAgICAgICJtYW1lbG9kaSIsDQogICAgICAic3VuZG93bnMiLA0KICAgICAgIm9mbWFnYXppbmVhdmFpbGFibGUiLA0KICAgICAgImNhc2FibGFuY2EiLA0KICAgICAgIm9wZWQiLA0KICAgICAgIm5ld3NkZWNrIiwNCiAgICAgICJlZGl0b3JpYWwiLA0KICAgICAgIm5ld2ZsYXNoIiwNCiAgICAgICJzb3V0aGFmcmljYW5tb3JuaW5nIiwNCiAgICAgICJuZXdzbGluayIsDQogICAgICAiZW5jYXMiLA0KICAgICAgInNvdXRoYWZyaWNhdG9uaWdodCIsDQogICAgICAidGhlbWlkZGF5dmlldyIsDQogICAgICAidGhlbGVhZCIsDQogICAgICAicHJvcGVydHltYXR0ZXJzIiwNCiAgICAgICJiYSIsDQogICAgICAia2EiLA0KICAgICAgInlhIiwNCiAgICAgICJnYSIsDQogICAgICAid2EiLA0KICAgICAgImxlIiwNCiAgICAgICJrd2EiLA0KICAgICAgIm1vcm5pbmdsaXZlc2FiYyIsDQogICAgICAibW9uZGF5IiwNCiAgICAgICJwcml4IiwNCiAgICAgICJhemVyYmFpamFuIiwNCiAgICAgICJlbmNhc2lzIiwNCiAgICAgICJlbmNhYnVzaW5lc3MiLA0KICAgICAgImVuY2Fzc3BlYWtzIiwNCiAgICAgICJzb3V0aCIsDQogICAgICAiYWZyaWNhIiwNCiAgICAgICJwbSIsDQogICAgICAic2EiLA0KICAgICAgInBtIiwNCiAgICAgICJlbmNhcyIsDQogICAgICAiaXNzIiwNCiAgICAgICJpY3ltaSIsDQogICAgICAidGltZXNsaXZlIiwNCiAgICAgICJmdWxsdmlldyIsDQogICAgICAibmV3c2JyZWFrc2p1bCIsDQogICAgICAibmV3c2JyZWFranVsIiwNCiAgICAgICJzYWJjIiwNCiAgICAgICJuY2EiLA0KICAgICAgIm5jYXMiLA0KICAgICAgIm9wIiwNCiAgICAgICJpZyIsDQogICAgICAiZWQiLA0KICAgICAgInBsIiwNCiAgICAgICJuZXdzMjQiLA0KICAgICAgIm5ld3MyNHMiLA0KICAgICAgImRtMTY4IiwNCiAgICAgICJzaW5lc3MiLA0KICAgICAgInVzaW5lc3MiLA0KICAgICAgImV3c2RlY2siLA0KICAgICAgIm9ybGQiLA0KICAgICAgInN1bmRheSIsDQogICAgICAiZnJpZGF5IiwNCiAgICAgICJzYXR1cmRheSIsDQogICAgICAidGh1cnNkYXkiLA0KICAgICAgIndlZG5lc2RheSIsDQogICAgICAibW9uZGF5IiwNCiAgICAgICJ0dWVzZGF5IiwNCiAgICAgICJwaWNzIiwNCiAgICAgICJsaXZlIg0KICAgICkNCiAgKQ0KDQojdGlkeSBkZiBhbmQgdW5uZXN0DQpyZWRkaXRfbWVkaWFfZGYgPC0gcmVkZGl0X3Bvc3RzX2RmICU+JQ0KICAjZmlsdGVyKHN0cl9kZXRlY3QodGV4dCwgZml4ZWQoY292aWRfZGljdGlvbmFyeSwgaWdub3JlX2Nhc2UgPSBUUlVFKSkpICU+JQ0KICB1bm5lc3RfdG9rZW5zKHdvcmQsIHRpdGxlLCB0b2tlbiA9ICJ0d2VldHMiKSAlPiUNCiAgZmlsdGVyKA0KICAgICF3b3JkICVpbiUgc3RvcF93b3JkcyR3b3JkLCF3b3JkICVpbiUgcmVkZGl0X3N0b3Bfd29yZHMkd29yZCwgDQogICAgIXdvcmQgJWluJSByZWRkaXRfbmVnYXRlZF93b3JkcyR3b3JkMiwgDQogICAgIXdvcmQgJWluJSBzdHJfcmVtb3ZlX2FsbChzdG9wX3dvcmRzJHdvcmQsICInIiksDQogICAgc3RyX2RldGVjdCh3b3JkLCAiW2Etel0iKQ0KICApDQoNCmBgYA0KDQpgYGB7ciB0b3Agd29yZHN9DQojdG9wIHdvcmRzDQp0b3Bfd29yZHNfcmVkZGl0IDwtIHJlZGRpdF9tZWRpYV9kZiAlPiUNCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JQ0KICBjb3VudCh3b3JkKSAlPiUNCiAgYXJyYW5nZShkZXNjKG4pKQ0KdG9wX3dvcmRzX3JlZGRpdCAlPiUNCiAgc2xpY2UoMToyMCkgJT4lDQogIGdncGxvdChhZXMocmVvcmRlcih3b3JkLC1uKSwgbiwgZmlsbCA9IHdvcmQpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KA0KICAgICAgYW5nbGUgPSA2MCwNCiAgICAgIGhqdXN0ID0gMSwNCiAgICAgIHNpemUgPSAxMw0KICAgICksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE4KQ0KICApICsNCiAgeWxhYigiRnJlcXVlbmN5IikgKw0KICB4bGFiICgiIikgKw0KICBnZ3RpdGxlKCJNb3N0IGZyZXF1ZW50IHJlZGRpdCBwb3N0cyIpICsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkNCmBgYA0KDQpgYGB7ciBiaWdyYW1zfQ0KI2JpZ3JhbXMNCnJlZGRpdF9iaWdyYW1fZGYgPC0gcmVkZGl0X3Bvc3RzX2RmICU+JQ0KICAjZmlsdGVyKHN0cl9kZXRlY3QodGV4dCwgZml4ZWQoY292aWRfZGljdGlvbmFyeSwgaWdub3JlX2Nhc2UgPSBUUlVFKSkpICU+JQ0KICBmaWx0ZXIoIXN0cl9kZXRlY3QodGl0bGUsICJeUlQiKSkgJT4lDQogIG11dGF0ZSh0aXRsZSA9IGdzdWIoIiA/KGZ8aHQpdHAocz8pOi8vKC4qKVsuXVthLXpdKyIsICIgIiwgdGl0bGUpKSAlPiUNCiAgdW5uZXN0X3Rva2VucyhiaWdyYW0sIHRpdGxlLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikgJT4lDQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKQ0KDQpyZWRkaXRfYmlncmFtc19maWx0ZXJlZCA8LSByZWRkaXRfYmlncmFtX2RmICU+JQ0KICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUNCiAgZmlsdGVyKCF3b3JkMiAlaW4lIHN0b3Bfd29yZHMkd29yZCkNCg0KIyBuZXcgYmlncmFtIGNvdW50czoNCnJlZGRpdF9iaWdyYW1fY291bnRzIDwtIHJlZGRpdF9iaWdyYW1zX2ZpbHRlcmVkICU+JQ0KICBjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQ0KDQpyZWRkaXRfYmlncmFtc191bml0ZWQgPC0gcmVkZGl0X2JpZ3JhbXNfZmlsdGVyZWQgJT4lDQogIHVuaXRlKGJpZ3JhbSwgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpDQoNCiN3ZWlnaHRzIGFuZCBncmFwaHMNCnJlZGRpdF9iaWdyYW1fZ3JhcGggPC0gcmVkZGl0X2JpZ3JhbV9jb3VudHMgJT4lDQogIGZpbHRlcihuID4gMTAwKSAlPiUNCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkNCg0KYGBgDQoNCmBgYHtyIG5lZ2F0aW9uIHdvcmRzfQ0KI3ZhZGVyIGxleGljb24gaW1wb3J0ZWQgZnJvbSBWQURFUiBHaXRIdWINCnJlZGRpdF92YWRlcl9sZXhpY29uIDwtIHJlYWRfY3N2MigiZGF0YV9pbi92YWRlcl9sZXhpY29uLmNzdiIpICU+JQ0KICByZW5hbWUoIndvcmQiID0gVE9LRU4sICJ2YWx1ZSIgPSBgTUVBTi1TRU5USU1FTlQtUkFUSU5HYCkNCg0KI2NvbW1vbiBuZWdhdGlvbiB3b3Jkcw0KbmVnYXRpb25fd29yZHMgPC0NCiAgYygNCiAgICAibm90IiwNCiAgICAibm8iLA0KICAgICJuZXZlciIsDQogICAgIndpdGhvdXQiLA0KICAgICJubyIsDQogICAgIm5vdCIsDQogICAgIm5vbmUiLA0KICAgICJubyBvbmUiLA0KICAgICJub2JvZHkiLA0KICAgICJub3RoaW5nIiwNCiAgICAibmVpdGhlciIsDQogICAgIm5vd2hlcmUiLA0KICAgICJuZXZlciIsDQogICAgImRvZXNu4oCZdCIsDQogICAgImlzbuKAmXQiLA0KICAgICJ3YXNu4oCZdCIsDQogICAgInNob3VsZG7igJl0IiwNCiAgICAid291bGRu4oCZdCIsDQogICAgImNvdWxkbuKAmXQiLA0KICAgICJ3b27igJl0IiwNCiAgICAiY2Fu4oCZdCIsDQogICAgImRvbuKAmXQiDQogICkNCnJlZGRpdF9uZWdhdGVkX3dvcmRzIDwtIHJlZGRpdF9iaWdyYW1fZGYgJT4lDQogIGZpbHRlcih3b3JkMSAlaW4lIGZpeGVkKG5lZ2F0aW9uX3dvcmRzLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSAlPiUNCiAgaW5uZXJfam9pbihyZWRkaXRfdmFkZXJfbGV4aWNvbiwgYnkgPSBjKHdvcmQyID0gIndvcmQiKSkgJT4lDQogIG11dGF0ZSh2YWx1ZSA9IGFzLmRvdWJsZSh2YWx1ZSkpICU+JQ0KICBjb3VudCh3b3JkMSwgd29yZDIsIHZhbHVlLCBzb3J0ID0gVFJVRSkgJT4lDQogIG11dGF0ZShjb250cmlidXRpb24gPSBuICogdmFsdWUpICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKGNvbnRyaWJ1dGlvbikpKSAlPiUNCiAgbXV0YXRlKHdvcmQyID0gcmVvcmRlcih3b3JkMiwgY29udHJpYnV0aW9uKSkNCnJlZGRpdF9uZWdhdGVkX3dvcmRzICU+JQ0KICBoZWFkKDQwKSAlPiUNCiAgZ2dwbG90KGFlcyhuICogdmFsdWUsIHdvcmQyLCBmaWxsID0gbiAqIHZhbHVlID4gMCkpICsNCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKCB+IHdvcmQxLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBsYWJzKHggPSAiU2VudGltZW50IHZhbHVlICogIyBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiLA0KICAgICAgIHkgPSAiV29yZHMgcHJlY2VkZWQgYnkgbmVnYXRpb24gdGVybXMiKQ0KDQpgYGANCg0KYGBge3IgQ291bnRpbmcgYW5kIGNvcnJlbGF0aW5nIGFtb25nIHNlY3Rpb25zLCB3YXJuaW5nPUZBTFNFfQ0KcmVkZGl0X3NlY3Rpb25fd29yZHMgPC0gcmVkZGl0X21lZGlhX2RmICU+JQ0KICBtdXRhdGUoc2VjdGlvbiA9IHJvd19udW1iZXIoKSAlLyUgMTApICU+JQ0KICBmaWx0ZXIoc2VjdGlvbiA+IDApDQoNCiMgY291bnQgd29yZHMgY28tb2NjdXJpbmcgd2l0aGluIHNlY3Rpb25zDQpyZWRkaXRfd29yZF9wYWlycyA8LSByZWRkaXRfc2VjdGlvbl93b3JkcyAlPiUNCiAgcGFpcndpc2VfY291bnQod29yZCwgc2VjdGlvbiwgc29ydCA9IFRSVUUpDQoNCiMgd2UgbmVlZCB0byBmaWx0ZXIgZm9yIGF0IGxlYXN0IHJlbGF0aXZlbHkgY29tbW9uIHdvcmRzIGZpcnN0DQpyZWRkaXRfd29yZF9jb3JzIDwtIHJlZGRpdF9zZWN0aW9uX3dvcmRzICU+JQ0KICBncm91cF9ieSh3b3JkKSAlPiUNCiAgZmlsdGVyKG4oKSA+PSAyMCkgJT4lDQogIHBhaXJ3aXNlX2Nvcih3b3JkLCBzZWN0aW9uLCBzb3J0ID0gVFJVRSkNCg0KcmVkZGl0X3dvcmRfY29ycyAlPiUNCiAgc2xpY2VfbWF4KGNvcnJlbGF0aW9uLCBuID0gNikgJT4lDQogIG11dGF0ZShpdGVtMiA9IHJlb3JkZXIoaXRlbTIsIGNvcnJlbGF0aW9uKSkgJT4lDQogIGdncGxvdChhZXMoaXRlbTIsIGNvcnJlbGF0aW9uKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBmYWNldF93cmFwKCB+IGl0ZW0xLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgY29vcmRfZmxpcCgpDQoNCnNldC5zZWVkKDEyMzQpDQpyZWRkaXRfd29yZF9jb3JzICU+JQ0KICBncmFwaF9mcm9tX2RhdGFfZnJhbWUoKSAlPiUNCiAgZ2dyYXBoKGxheW91dCA9ICJmciIpICsNCiAgZ2VvbV9lZGdlX2xpbmsoYWVzKGVkZ2VfYWxwaGEgPSBjb3JyZWxhdGlvbiksDQogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsDQogICAgICAgICAgICAgICAgIGVkZ2Vfd2lkdGggPSAzKSArDQogIGdlb21fbm9kZV9wb2ludChjb2xvciA9ICJsaWdodGJsdWUiLCBzaXplID0gNSkgKw0KICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBUUlVFKSArDQogIHRoZW1lX3ZvaWQoKQ0KYGBgDQoNCmBgYHtyIFZBREVSfQ0KIyB2YWRlcl9kZiA8LSB2YWRlcl9kZihyZWRkaXRfcG9zdHNfZGYkdGl0bGUpDQojIHdyaXRlX2FzX2Nzdih2YWRlcl9kZiwgImRhdGFfaW4vdmFkZXJfcmVkZGl0X3Bvc3RzIikNCg0KdmFkZXJfZGYgPC0gcmVhZF9jc3YoImRhdGFfaW4vdmFkZXJfcmVkZGl0X3Bvc3RzLmNzdiIpDQp2YWRlcl9kZiA8LSB2YWRlcl9kZiAlPiUgbXV0YXRlKCJYMSIgPSByb3dfbnVtYmVyKCkpDQpyZWRkaXRfcG9zdHNfZGYgPC0gcmVkZGl0X3Bvc3RzX2RmICU+JSBtdXRhdGUoIlgxIiA9IHJvd19udW1iZXIoKSkNCnJlZGRpdF92YWRlcl9kZiA8LSByZWRkaXRfcG9zdHNfZGYgJT4lIGxlZnRfam9pbih2YWRlcl9kZiwgYnkgPSAiWDEiKQ0KDQojR2VuZXJhbCBzZW50aW1lbnQgb3ZlciB0aW1lLiBNZWRpYSBhZ2VuY2llcyBzZWVtIHRvIGhhdmUgYW4gZXZlbiBudW1iZXIgb2YgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHR3ZWV0cyBwZXIgZGF5Lg0KZ2dwbG90KA0KICByZWRkaXRfdmFkZXJfZGYgJT4lDQogICAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKSAlPiUNCiAgICBncm91cF9ieShkYXRlKSAlPiUNCiAgICBtdXRhdGUoY29tcG91bmQgPSByZXBsYWNlKGNvbXBvdW5kLCBpcy5uYShjb21wb3VuZCksIDApKSAlPiUNCiAgICBzdW1tYXJpc2Uoc3VtX2NvbXBvdW5kID0gc3VtKGFzLmRvdWJsZShjb21wb3VuZCkpKSwNCiAgYWVzKGRhdGUsIHN1bV9jb21wb3VuZCkNCikgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBuYS5ybSA9IFRSVUUsIHNlID0gRkFMU0UpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsNCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjMgZGF5IiwgZGF0ZV9sYWJlbHMgPSAiJW0tJWQiKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KA0KICAgICAgYW5nbGUgPSA5MCwNCiAgICAgIHZqdXN0ID0gMC41LA0KICAgICAgaGp1c3QgPSAxDQogICAgKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLA0KICApDQojIEFuIGlsbGVnYWwgZ29sZCBtaW5lciB3aG8gd2FzIHNldmVyZWx5IGluanVyZWQgaW4gYSBjbGFzaCBpbiB3aGljaCBmb3VyIG90aGVyIGlsbGVnYWwgbWluZXJzIHdlcmUga2lsbGVkIGhhcyBiZWVuIGNoYXJnZWQgZm9yIHRoZWlyIG11cmRlcnMgTXB1bWFsYW5nYSBwb2xpY2Ugc2FpZCBvbiBUaHVyc2RheQ0KIyBJdGFseSBtaWRmaWVsZGVyIEpvcmdpbmhvIHNhaWQgdGVhbSBnbG9yeSBpcyBtb3JlIGltcG9ydGFudCB0aGFuIGFueSBwdXNoIHRvIHdpbiBhIHN1cnByaXNlIEJhbGxvbiBk4oCZT3IgYXdhcmQgZm9yIHRoZSBiZXN0IHBsYXllciBpbiB3b3JsZCBmb290YmFsbCBhZnRlciBhIHRlYW1tYXRlIHNhaWQgaGUgZGVzZXJ2ZWQgaXQNCg0KZ2dwbG90KA0KICByZWRkaXRfdmFkZXJfZGYgJT4lDQogICAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKSAlPiUNCiAgICBncm91cF9ieShkYXRlKSAlPiUNCiAgICBzdW1tYXJpc2UoY29tcG91bmQpLA0KICBhZXMoZGF0ZSwgY29tcG91bmQpDQopICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbmEucm0gPSBUUlVFKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKQ0KDQojTmV3cyBzZW50aW1lbnQNCnJlZGRpdF92YWRlcl9kZiAlPiUNCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpKSAlPiUNCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lDQogIHN1bW1hcmlzZShjb21wb3VuZCkgJT4lDQogIGFycmFuZ2UoZGVzYyhjb21wb3VuZCkpDQoNCmdncGxvdChyZWRkaXRfdmFkZXJfZGYgJT4lIGFycmFuZ2UoY29tcG91bmQpICU+JSBtdXRhdGUoWDEgPSBmYWN0b3IoWDEsIGxldmVscyA9IFgxKSksDQogICAgICAgYWVzKHggPSBYMSkpICsNCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gIGFlcyh5ID0gY29tcG91bmQpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKQ0KDQpyZWRkaXRfdmFkZXJfZGYgJT4lDQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlKSkgJT4lDQogIGdyb3VwX2J5KGRhdGUpICU+JQ0KICBtdXRhdGUoY29tcG91bmQgPSByZXBsYWNlKGNvbXBvdW5kLCBpcy5uYShjb21wb3VuZCksIDApKSAlPiUNCiAgc3VtbWFyaXNlKHN1bV9jb21wb3VuZCA9IHN1bShhcy5kb3VibGUoY29tcG91bmQpKSkNCmBgYA0KDQpgYGB7ciBJbnRlcmFjdGlvbnMsIGVjaG89RkFMU0V9DQojIHJlZGRpdF92YWRlcl9kZiAlPiUgc2VsZWN0KGZhdm9yaXRlX2NvdW50LCByZXR3ZWV0X2NvdW50KSAlPiUgbXV0YXRlKGZhdm9yaXRlX2NvdW50ICsgcmV0d2VldF9jb3VudCkNCg0KcmVkZGl0X3ZhZGVyX2RmIDwtIHJlZGRpdF92YWRlcl9kZiAlPiUNCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUsIGZvcm1hdCA9ICIlZC0lbS0leSIpKSAlPiUNCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lDQogIG11dGF0ZSgNCiAgICBudW1fY29tbWVudHMgPSBtZWFuKG51bV9jb21tZW50cykNCiAgKQ0KIyBtZWFuIGZvciB0aGUgZGF5DQpyZWRkaXRfaW50ZXJhY3Rpb25zX3Bsb3QgPC0gZ2dwbG90bHkoDQogIGdncGxvdChkYXRhID0gcmVkZGl0X3ZhZGVyX2RmLCBhZXMoZGF0ZSkpICsNCiAgICBnZW9tX3JpYmJvbihhZXMoDQogICAgICB5bWluID0gMCwgeW1heCA9IG51bV9jb21tZW50cywgZmlsbCA9ICJudW1fY29tbWVudHMiDQogICAgKSkgKw0KICAgIHRoZW1lKA0KICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIA0KICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDApLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLCAwKSwNCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgICAgc2l6ZSA9IDE0LA0KICAgICAgICBmYWNlID0gImJvbGQiLA0KICAgICAgICBtYXJnaW4gPSBtYXJnaW4oMCwgMCwgMTAsIDApLA0KICAgICAgICBoanVzdCA9IDANCiAgICAgICksDQogICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwKSwNCiAgICApDQopDQoNCnJlZGRpdF9pbnRlcmFjdGlvbnNfcGxvdA0KYGBgDQoNCmBgYHtyIFRvcGljIE1vZGVsbGluZ30NCnJlZGRpdF9tYXRyaXggPC0NCiAgcmVkZGl0X21lZGlhX2RmICU+JSAgY291bnQoc3VicmVkZGl0LCB3b3JkKSAlPiUgY2FzdF9kZm0oc3VicmVkZGl0LCB3b3JkLCBuKQ0KDQpyZWRkaXRfbWVkaWFfbGRhIDwtIExEQShyZWRkaXRfbWF0cml4LCBrID0gMywgY29udHJvbCA9IGxpc3Qoc2VlZCA9IDEyMzQpKQ0KDQpyZWRkaXRfbWVkaWFfdG9waWNzIDwtIHRpZHkocmVkZGl0X21lZGlhX2xkYSwgbWF0cml4ID0gImJldGEiKQ0KDQpyZWRkaXRfbWVkaWFfdG9wX3Rlcm1zIDwtIHJlZGRpdF9tZWRpYV90b3BpY3MgJT4lDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgc2xpY2VfbWF4KGJldGEsIG4gPSAxMCkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgYXJyYW5nZSh0b3BpYywtYmV0YSkNCg0KcmVkZGl0X21lZGlhX3RvcF90ZXJtcyAlPiUNCiAgbXV0YXRlKHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykpICU+JQ0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gdGVybSwNCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IHRvcGljLA0KICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGJldGEpICU+JQ0KICByZW5hbWUoDQogICAgInRvcGljIDEiID0gMiwNCiAgICAidG9waWMgMiIgPSAzLA0KICAgICJ0b3BpYyAzIiA9IDQNCiAgKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDIsIDMsIDQpLA0KICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAidG9waWMiLA0KICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImJldGEiKSAlPiUNCiAgZHJvcF9uYSgpICU+JQ0KICBnZ3Bsb3QoYWVzKGJldGEsIHRlcm0sIGZpbGwgPSBmYWN0b3IodG9waWMpKSkgKw0KICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAoIH4gdG9waWMsIHNjYWxlcyA9ICJmcmVlIikgKw0KICBzY2FsZV95X3Jlb3JkZXJlZCgpDQpgYGANCg0KYGBge3IgR2FwIGsganVzdGlmeX0NCmxpYnJhcnkoImxkYXR1bmluZyIpDQpsaWJyYXJ5KCJ0b3BpY21vZGVscyIpDQoNCmRhdGEoIkFzc29jaWF0ZWRQcmVzcyIsIHBhY2thZ2UgPSAidG9waWNtb2RlbHMiKQ0KZHRtIDwtIEFzc29jaWF0ZWRQcmVzc1sxOjEwLF0NCg0KcmVzdWx0IDwtIEZpbmRUb3BpY3NOdW1iZXIoDQogIHJlZGRpdF9tYXRyaXgsDQogIHRvcGljcyA9IHNlcShmcm9tID0gMiwgdG8gPSAxNSwgYnkgPSAxKSwNCiAgbWV0cmljcyA9IGMoIkdyaWZmaXRoczIwMDQiLCAiQ2FvSnVhbjIwMDkiLCAiQXJ1bjIwMTAiLCAiRGV2ZWF1ZDIwMTQiKSwNCiAgbWV0aG9kID0gIkdpYmJzIiwNCiAgY29udHJvbCA9IGxpc3Qoc2VlZCA9IDc3KSwNCiAgbWMuY29yZXMgPSAyTCwNCiAgdmVyYm9zZSA9IFRSVUUNCikNCg0KRmluZFRvcGljc051bWJlcl9wbG90KHJlc3VsdCkNCmBgYA0K